﻿'RecFinder v1.0 -- RELEASE --
'A Simple App for Interacting and Searching through databases
'Project Leader,Commiter,Designer = Alagkiozidis Eleftherios (elpalag@it.teithe.gr / golathra@gmail.com)
'Project Member and Revision Commiter = Tsiokas Evaggelos (tsiokasvag@gmail.com)
'Project Member and Revision Commiter = Isaia Xasapi (ichasapi6@gmail.com)
'Project Member and Revision Commiter = Xatzigianni Dora (xatzigiannidora@gmail.com)
'Overall Project Supervisor = Michalis Salampasis, Associate professor at IT Departments Of ATEI Thessaloniki

'This is the vb2008 (and final) Edition of RecFinder, it will
'be implemented on 2010 in future edition with .NET 4.0

'All Comments are on English Language For Compability Issues
'RecFinder Source Code is under GNU GPL Licence 3 -- Just to Know ;-)
'-----------------------------------------------------------------------
Imports System.IO
Imports System.Data.SqlClient
Imports System.Data.OleDb
Imports System.Data.Common
Imports Microsoft.VisualBasic.FileIO
Imports System.Text.RegularExpressions
Imports Microsoft.Win32.RegistryKey
Imports System.Security.AccessControl

Public Class Main
    Public RegistryReadOnly As Boolean = False 'Checks whenever registry is readonly or not
    Public defaultPath As String = My.Settings.pathToLogs 'Holds default path, in case registry is not readable
    Public filepath As String 'Global and Public Variable for determining filepath of database file
    Public currentTable As String 'Global and Public Variable which holds the current selected table to work with
    Dim andFlag As Boolean = False 'Checks if user specified a filter in more than one columns
    Dim str As String = String.Empty
    Dim primarykeys As New List(Of String)
    Dim foreignkeys As New List(Of String)

    Private Sub DataBaseConn() 'This function will perform database connection
        Dim statement As String
        statement = "SELECT * FROM " & currentTable    'This is a variable that stores a sql Statement with the table we selected from tableList ListBox"

        Dim conn As New OleDbConnection       'This will be used to connect to db
        conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filepath 'The connectionstring through the database file

        Try

            Using adapter As New OleDbDataAdapter(statement, conn.ConnectionString) 'This adapter will be used for the interaction with Database
                Dim dst As New DataSet  'This dataset will do most of the job
                adapter.Fill(dst, currentTable) 'Dataset fills with the table we give
                MainView.DataSource = dst.Tables(currentTable)  'The Datagrid takes the table and shows it


                Dim i As Integer = 0
                For Each dcol As DataColumn In dst.Tables(currentTable).Columns 'This For-Each Loop fills the Criteria-DataGrid with columns of table


                    Dim cols As String() = New String() {dcol.ToString} 'Fill the string-array with all the columns
                    criteriaGrid.Rows.Add(cols) 'add the columns to datagrid
                    tableInfo.Rows.Add(cols) 'add the columns also to datagrid TableInfo


                Next dcol

                For index As Integer = 0 To tableInfo.RowCount - 2 'This For-Loop traverses the entire datagrid to add data

                    tableInfo.Rows(index).Cells(1).Value = dst.Tables(currentTable).Columns(index).DataType.ToString 'the third cell gets the datatype of column

                Next index

                str = dst.GetXml.ToString 'Get xml data if user wishes to save xml

            End Using

        Catch ex As Exception 'This is in case something goes wrong
            MsgBox("An Error Occured", MsgBoxStyle.Critical)

        End Try

        QueryBox.Enabled = True 'Enable Query Box
        QueryBox.Clear() 'Empty Query Box for getting the new statement
        QueryBox.Text = statement 'Give the statement to the Query Box
        'Enable User Controls
        exec.Enabled = True
        qryBuild.Enabled = True
        qManage.Enabled = True
        qSave.Enabled = True
        btnprint.Enabled = True
        SaveFileToolStripMenuItem.Enabled = True
        SaveAsXMLFileToolStripMenuItem.Enabled = True
        chMode.Enabled = True


    End Sub

    Private Sub ExitRecFinderToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitRecFinderToolStripMenuItem.Click
        Me.Close() 'This Sub-Menu terminates the Application
    End Sub

    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        QueryBox.Enabled = False 'This Prevents users from writing queries when a database is not open
        MainView.ReadOnly = True 'Makes MainView DataGrid Read-Only so user will not be able to alter it in any way by mistake
        qManage.Enabled = False
        qSave.Enabled = False
        btnprint.Enabled = False
        exec.Enabled = False
        qryBuild.Enabled = False
        desscBox.ReadOnly = True 'Description Box is ReadOnly (fills if user loads a query from DB)
        desscBox.Enabled = False 'Disable Description Box (activates only if user loads a saved query from db)
        SaveFileToolStripMenuItem.Enabled = False 'Disable save query to file menu entry
        SaveAsXMLFileToolStripMenuItem.Enabled = False 'and so the save xml menu entry
        chMode.Enabled = False 'disable command mode toggle before dbs are loaded

        If My.Settings.ShowKeys = True Then 'check if user want to see keys info or not
            '3/1/2013 FIXES
            'Now Labels Properly hide themselves when user sets to hide them along with the tables

            keysInfo.Visible = True
            lblKeys.Visible = True '<-- FIX
        Else
            keysInfo.Visible = False '<-- Fix
            lblKeys.Visible = False
        End If



        If My.Settings.ShowTypes = True Then 'check if user want to see field types info or not
            lblInfo.Visible = True '<--FIX
            tableInfo.Visible = True
        Else
            tableInfo.Visible = False '<-- FIX
            lblInfo.Visible = False
        End If


        If My.Settings.pathToLogs = "" Then 'If pathToLogs is empty
            My.Settings.pathToLogs = My.Settings.defaultLogPath 'use the default one
            defaultPath = My.Settings.pathToLogs 'and update the local variable

        End If

        '-----------------------------------------------------------------------------------------------------------------------------------------
        'Un-Comment theese lines if your registry does not allow manipulation
        'Start VB as Administrator and Shoot 

        'Using key As Microsoft.Win32.RegistryKey = My.Computer.Registry.LocalMachine.OpenSubKey("Software\RecFinder\recfinder_connString", True)
        '    Dim regSec As RegistrySecurity = key.GetAccessControl(AccessControlSections.All)
        '    Dim rule As New RegistryAccessRule("Everyone", RegistryRights.FullControl, _
        '        InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow)
        '    regSec.AddAccessRule(rule)
        '    key.SetAccessControl(regSec)
        'End Using
        '-----------------------------------------------------------------------------------------------------------------------------------------

        If My.Settings.RegistryAccessible = True Then

            Try
                'We will Create Registry Keys for the Application
                'Using try-catch because registry may be not accessible if user has insufficient rights to do so
                Dim regkey As Microsoft.Win32.RegistryKey = My.Computer.Registry.LocalMachine.CreateSubKey("Software\RecFinder\recfinder_connString", Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree) 'Create a Registry Key that stores the log Database path
                My.Computer.Registry.SetValue("HKEY_LOCAL_MACHINE\Software\RecFinder\recfinder_connString", "path", My.Settings.pathToLogs) 'Set the Default Registry Path Setting
                My.Settings.RegistryAccessible = True 'Mark Registry as Accessble
                pathInUse.Text = "Using : Registry path (Registry Active)"
            Catch ex As Exception 'In case Registry is not write/read capable due to insufficient rights....(thats the reason for exception to occur)
                MsgBox("Registry is not Acessible, using default settings", MsgBoxStyle.Exclamation) 'Notify user
                My.Settings.RegistryAccessible = False 'And Flag registry as readonly
            End Try
        Else
            pathInUse.Text = "Using : Default Path (Registry is disabled)"
        End If


    End Sub
    Private Sub AboutRecfinderToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AboutRecfinderToolStripMenuItem.Click
        aboutDialog.Show() 'Shows the About RecFinder Dialog
    End Sub

    Private Sub GetTables()
        Dim ConnString As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & filepath 'This Will Be Used as ConnectionString to Re-Connect to Database
        'We Need The Tables of the Database
        Dim SchemaTable As DataTable 'This Variable Takes The DataBase Table Names
        Dim conn As New OleDbConnection(ConnString) 'This Will Be used for Connection
        Dim primaryKey As New List(Of String) 'This list is for keeping the schema primary keys
        Dim pk_temp As New List(Of String) 'this list is the temporary storage of primary keys
        Dim pk_table As New List(Of String) 'this is for keeping the tables which the primary keys belong
        Dim pkt_temp As New List(Of String) 'and this is the temporary storage space for them
        Dim fk_table As New List(Of String) 'this will keep the tables in which the foreign keys are
        Dim fkt_temp As New List(Of String) 'and this is the temp storage space for them
        Dim fk_col As New List(Of String) 'this is the foreign key columns
        Dim fkc_temp As New List(Of String) 'and temp storage for them
        Dim fk_name As New List(Of String) 'finally this keeps the foreign key constraint name
        Dim fkn_temp As New List(Of String) 'and the temp storage space for them


        Try
            tableList.Items.Clear() 'First Clear the TableList ListBox
            conn.Open() 'Open DB Connection
            'This line gets all the Schema tables
            SchemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, Nothing}) 'Get Tables


            For i As Integer = 0 To SchemaTable.Rows.Count - 1 Step 1 'for-loop that traverse through schematable
                If SchemaTable.Rows(i)!TABLE_TYPE.ToString = "TABLE" Then 'if type = table 
                    tableList.Items.Add(SchemaTable.Rows(i)!TABLE_NAME.ToString()) 'Fill The ListBox
                End If
            Next

            Dim keysTable As DataTable 'This Datatable will hold the Schema Keys
            keysTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Foreign_Keys, Nothing) 'Fills with the foreign/primary keys (they both exist in this schema)

            For parse As Integer = 0 To keysTable.Rows.Count - 1 'Traverse through the table

                pkt_temp.Add(keysTable.Rows(parse).ItemArray(2).ToString) 'Add primary key table to temp pkt list
                pk_temp.Add(keysTable.Rows(parse).ItemArray(3).ToString) 'Add primary key field to temp pk list
                fkt_temp.Add(keysTable.Rows(parse).ItemArray(8).ToString) 'Add foreign key table to temp fkt list
                fkc_temp.Add(keysTable.Rows(parse).ItemArray(9).ToString) 'Add foreign key field to temp fk list
                fkn_temp.Add(keysTable.Rows(parse).ItemArray(16).ToString) 'Add constraint name to temp fkn list 


            Next

            keysInfo.Rows.Clear() 'Empty the keysinfo datagrid


            For i As Integer = 0 To keysTable.Rows.Count - 1 'Traverse again through the keystable

                'Move all data from temp lists to the permanent ones....

                primaryKey.Add(pk_temp(i).ToString)
                pk_table.Add(pkt_temp(i).ToString)

                fk_table.Add(fkt_temp(i).ToString)
                fk_col.Add(fkc_temp(i).ToString)
                fk_name.Add(fkn_temp(i).ToString)
                keysInfo.Rows.Add(primaryKey(i) & " in " & pk_table(i)) 'Displays <Primary Key> in <Table> / Fill Datagrid

            Next

            Dim index As Integer = 0

            For i As Integer = 0 To keysInfo.Rows.Count - 2 Step 1 'Traverse to the datagrid keysinfo

                keysInfo.Rows(i).Cells(1).Value = fk_col(i) & " in " & fk_table(i) '<Foreign key> in <Table> / Fill datagrid
                keysInfo.Rows(i).Cells(2).Value = fk_name(i)


            Next i

        Catch ex As Exception
            MsgBox("Data Load Error", MsgBoxStyle.Critical) 'In Case Something Goes Wrong!
        End Try

        conn.Close() 'Close The Connection when finished
    End Sub

    Private Sub OpenToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenToolStripMenuItem.Click
        'This is a File Open Dialog, for selecting a database file to work with
        fileOpen.Title = "Select DataBase File" 'The File Open Dialog Window Title
        fileOpen.InitialDirectory = "C:/" 'Start from C:/ as default search path
        fileOpen.Filter = "MS Access Database (*.mdb)|*.mdb|All Files (*.*)|*.*" 'A pattern for showing only mdb files (or all files)
        fileOpen.FileName = "" 'File name must be blank first, afterwards when user selects file, it will be updated with full path
        fileOpen.ShowDialog() 'Activate Dialog (Show)

        filepath = fileOpen.FileName 'This Variable stores the full path for connection with the DataBase

        If fileOpen.FileName = "" Then 'If user does not select a file to open (clicks cancel)
            tableList.Items.Clear() 'Clear List of Tables so user can't select any non-existing table
            Return 'Stop and get out (so no exception will occur)
        End If

        GetTables()

        'DataBaseConn() 'Open File and Connect to Database (call Databasecon function) - Temp
    End Sub

    Private Sub exec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles exec.Click

        '----------------------------------------------------------------------

        'words can not exectute by button Execute Query
        Dim forbidenWords() As String = {"insert", "INSERT", "update", "UPDATE", "drop", "DROP", "delete", "DELETE", "constraint", "CONSTRAINT", "create", "CREATE"} 'Forbidden Statements
        For parser As Integer = 0 To forbidenWords.Length - 1 'For-Loop to search all the "forbidden" words in the arrat
            If QueryBox.Text.Contains(forbidenWords(parser)) Then 'if one of theese is contained inside the querybox....
                MsgBox("Non-Select Queries Are Not Allowed", MsgBoxStyle.Exclamation) 'Notify User...
                QueryBox.Clear() 'Clear the QueryBox,not to provoke an exception
                Return 'and get out of the Function immidiatelly
            End If
        Next parser

        executeQuery(QueryBox.Text) 'calls executeQuery function with querybox text as an arg (statement)

    End Sub
    Public Sub executeQuery(ByVal sqlqry As String)
        'This Function Connects to the DataBase and Executes Queries from the Query Box

        Dim conn As New OleDbConnection       'This will be used to connect to db
        conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filepath 'The connectionstring through the database file

        Try

            Using adapter As New OleDbDataAdapter(sqlqry, conn.ConnectionString) 'This adapter will be used for the interaction with Database
                Dim dst As New DataSet  'This dataset will do most of the job
                adapter.Fill(dst, currentTable) 'Dataset fills with the table we give
                MainView.DataSource = dst.Tables(currentTable)  'The Datagrid takes the table and shows it
                CommandMode.cmdGrid.DataSource = dst.Tables(currentTable)


            End Using



        Catch ex As Exception 'This is in case something goes wrong
            MsgBox("Invalid or No Query", MsgBoxStyle.Exclamation)
        End Try
    End Sub

    Private Sub btnprint_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnprint.Click
        printToFile() 'Call Print Function
    End Sub
    Private Sub printToFile() 'This Function Saves Query in a file with the description if available

        Dim savepath As String 'This String holds the path to the file save location

        filesave.Title = "Save Query to a File"
        filesave.InitialDirectory = "C:/" 'Start from C:/ as default search path
        filesave.Filter = "Rec Finder Query Extract (*.txt)|*.txt" 'A pattern for showing only rcf files (or all files)

        'filesave.ShowDialog() 'Activate Dialog (Show)

        If filesave.ShowDialog = Windows.Forms.DialogResult.OK Then 'Show the Dialog, and see if user clicked OK (Apothikefsi is OK)

            savepath = filesave.FileName 'The variable gets the path


            Dim fstream As FileStream 'Declaring a filestream variable (initialization in try block)
            Dim writer As StreamWriter 'Declaring a StreamWriter variable (init in try block)

            Try
                fstream = New FileStream(savepath, FileMode.Create, FileAccess.Write) 'FileStream with savepath, file creation and write on it 
                writer = New StreamWriter(fstream) 'File Writer to a file, stream writer

                If desscBox.Text <> "" Then 'If Description Box Holds a Description....

                    writer.WriteLine("RecFinder v1.0 Query Exctract")
                    writer.WriteLine("-----------------------------")
                    writer.WriteLine(vbNewLine)
                    writer.WriteLine("Query")
                    writer.WriteLine("-----")
                    writer.WriteLine(String.Format("{0}{1}", QueryBox.Text, vbNewLine)) 'user Query and another new line
                    writer.WriteLine("Description")
                    writer.WriteLine("-----------")
                    writer.WriteLine(String.Format("{0}{1}", desscBox.Text, vbNewLine)) 'description and another new line
                    writer.WriteLine(String.Format("Created On --> {0}", Now)) 'current time stamp


                Else 'Else, write the query to file without description
                    writer.WriteLine("RecFinder v1.0 Query Exctract")
                    writer.WriteLine("-----------------------------")
                    writer.WriteLine(vbNewLine)
                    writer.WriteLine("Query")
                    writer.WriteLine("-----")
                    writer.WriteLine(String.Format("{0}{1}", QueryBox.Text, vbNewLine)) 'user Query and another new line
                    writer.WriteLine("Description")
                    writer.WriteLine("-----------")
                    writer.WriteLine(String.Format("{0}{1}", "* No Description available *", vbNewLine)) 'no description message and another new line
                    writer.WriteLine(String.Format("Created On --> {0}", Now)) 'current time stamp


                End If


                writer.Close() 'Close Stream
                MsgBox("File Saved Sucessfully", MsgBoxStyle.Information) 'All Done
            Catch ex As Exception
                'writer.Flush()
                'writer.Close()
                MsgBox("File Write Error", MsgBoxStyle.Critical) 'Throw a MsgBox is something goes wrong
                Return

            End Try
            writer.Close() 'As long as you finish, close the file
        Else 'If user clicks Cancel
            Exit Sub 'Exit the Subrutine and do nothing
        End If
    End Sub

    Private Sub SaveFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveFileToolStripMenuItem.Click
        printToFile() 'File save from datagrid. Like the Print to File Button
    End Sub
    Private Sub tableList_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tableList.SelectedIndexChanged
        currentTable = tableList.SelectedItem.ToString 'Get the table name and save it to currenttable variable

        criteriaGrid.Rows.Clear() 'Clear DataGrid Each Time you select a new Table
        tableInfo.Rows.Clear() 'Clear Datagrid TableInfo everytime user selects a new table from Table-Selection
        desscBox.Clear() 'so does description


        DataBaseConn() 'Connect to Database and open the table
    End Sub

    Private Sub qryBuild_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles qryBuild.Click 'Applications Main Operation Function, Filtering and QueryBuilding....
        'FIXED -- NOW OPERATES PROPERLY
        Dim columns As String = String.Empty 'DataBase Table Columns
        Dim visibleColumn As String = String.Empty 'Columns that user chooses to show 
        Dim filter As String = String.Empty ' The filters that user specified per column
        Dim aliases As String = String.Empty ' Gets the Columns Aliases ( Column AS Name) if user wishes to
        Dim orderStatement As String = "ORDER BY" ' The Order By Clause base
        Dim ascStatement = "ASC" 'ASCending Mode
        Dim descStatement = "DESC" 'DESCending Mode
        Dim finalOrderStatement As String = String.Empty ' Assemble ORDER BY Clause (ORDER BY ASC|DESC)
        Dim or1 As String = String.Empty 'First OR Clause
        Dim or2 As String = String.Empty 'SEcond OR Clause
        Dim or3 As String = String.Empty 'Third OR Clause
        Dim finalQuery = String.Empty 'This variable will contain the final assembled query
        Dim tempQ As New ArrayList 'This ArrayList will hold every single condition user specifies in filter data Grid

        desscBox.Clear() 'Clear description box before everything

        For i = 0 To criteriaGrid.RowCount - 1 'Traversing Through the DataGrid View!

            If criteriaGrid.Rows(i).Cells(1).Value <> Nothing Then 'Check if user specified an Alias for the Particular Column
                aliases = " AS " & criteriaGrid.Rows(i).Cells(1).Value & " "
            End If

            If criteriaGrid.Rows(i).Cells(2).Value = True Then 'Now check which column user chose for showing 
                visibleColumn += criteriaGrid.Rows(i).Cells(0).Value & aliases & ", " 'Add the column with the alias (if any)
                aliases = String.Empty 'Empty Aliases to prevend double-records (2 columns with the same alias) 

            End If

            If criteriaGrid.Rows(i).Cells(3).Value = "Ascending" Then 'If user selected Ascending, order by clause will get ASC Mode
                finalOrderStatement = orderStatement & " " & criteriaGrid.Rows(i).Cells(0).Value & " " & ascStatement
            ElseIf criteriaGrid.Rows(i).Cells(3).Value = "Descending" Then 'Else it will take DescMode 
                finalOrderStatement = orderStatement & " " & criteriaGrid.Rows(i).Cells(0).Value & " " & descStatement
            End If 'No Ordering or no choice means no order, so don't add order statement

            If criteriaGrid.Rows(i).Cells(4).Value <> Nothing Then 'Now, the basic part of the application, user specified filter
                filter &= criteriaGrid.Rows(i).Cells(0).Value & " " & criteriaGrid.Rows(i).Cells(4).Value 'If found any, add it to filter variable
                'tempQ will get the word ' ) AND ( ' and the filter cell value (unnecessary AND will be removed further below)
                tempQ.Add(" ) AND ( " & criteriaGrid.Rows(i).Cells(0).Value & " " & criteriaGrid.Rows(i).Cells(4).Value)



            End If

            If criteriaGrid.Rows(i).Cells(5).Value <> Nothing Then ' First OR clause, if found any add it on or1
                or1 = " OR " & criteriaGrid.Rows(i).Cells(0).Value & " " & criteriaGrid.Rows(i).Cells(5).Value
                tempQ.Add(or1)
            End If

            If criteriaGrid.Rows(i).Cells(6).Value <> Nothing Then ' Second OR clause, if found any add it on Or2
                or2 = " OR " & criteriaGrid.Rows(i).Cells(0).Value & " " & criteriaGrid.Rows(i).Cells(6).Value
                tempQ.Add(or2)

            End If


            If criteriaGrid.Rows(i).Cells(7).Value <> Nothing Then ' Third OR clause, if found any add it on or3
                or3 = " OR " & criteriaGrid.Rows(i).Cells(0).Value & " " & criteriaGrid.Rows(i).Cells(7).Value
                tempQ.Add(or3)

            End If


        Next i 'For Loop Ends Here, it means that Criteria DataGrid reached its end


        'Now its time to Assemble the Query and Send it to QueryBox for User to execute it


        If visibleColumn = Nothing And filter = Nothing Then 'First Check if user has selected a column and if he/she specified a filter
            finalQuery = "SELECT * " & vbNewLine & "FROM " & currentTable & vbNewLine _
            & "WHERE 1 " & vbNewLine & finalOrderStatement
            QueryBox.Text = finalQuery
            Return 'When Finished, get out
        ElseIf visibleColumn = Nothing And filter <> Nothing Then 'If the above fail, it means that user specified a filter, so check for columns only


            'FIX APPLY (3/1/2013) --->
            Dim tempCondition As String = String.Empty 'This String will have the morph " ) AND ( <QUERY CONDITIONS> "
            Dim realCondition As String = String.Empty 'This will hold the clean and usable where condition

            For Each qrow As String In tempQ 'For each row in tempQ
                tempCondition &= qrow 'Fill the tempCondition string with everything in it
            Next


            'Now we should 'trim' the string, we use Mid (median) function
            'as you see, we say realCondition will be equal to mid(tempCondition)
            'if we cound the fist word characters ' ) AND ( ' from first space to D are 6 characters
            'so we start from character 7 (first space after D) until we reach the end of string
            'final step is to append ' ) ' symbol so Where Clause Condition will be like this
            ' (condition 1 [OR condition2]) [AND (condition2 OR [condition3) ] ) <-- this is our parenthesis

            realCondition = Mid(tempCondition, 7, tempCondition.Length) & " ) "


            'Final Query gets the full assembled query like this 
            'SELECT * <cr> FROM 'tablename' <cr> WHERE 'conditions' <cr> [ORDER BY 'tablename' ASC/DESC]

            '<--- FIX APPLY

            finalQuery = "SELECT * " & vbNewLine & "FROM " & currentTable & vbNewLine _
            & "WHERE " & realCondition & vbNewLine & finalOrderStatement


            QueryBox.Text = finalQuery 'Send it to Query Box, ready for execution

            Return 'When Finished, get out
        End If

        If filter = String.Empty Then 'Now Check about filters, if none specified , where clause will stay to default status (WHERE 1)
            finalQuery = "SELECT " & visibleColumn.Remove(visibleColumn.Length - 2) & " " & vbNewLine & _
        "FROM " & currentTable & " " & vbNewLine & "WHERE 1 " & vbNewLine & _
        finalOrderStatement
        Else 'If else block is executed, it means that user specified a filter, so add it to the query
            'FIX APPLY (3/1/2013)--->
            Dim tempCondition As String = String.Empty 'This String will have the morph " ) AND ( <QUERY CONDITIONS> "
            Dim realCondition As String = String.Empty 'This will hold the clean and usable where condition

            For Each qrow As String In tempQ 'For each row in tempQ
                tempCondition &= qrow 'Fill the tempCondition string with everything in it
            Next
            realCondition = Mid(tempCondition, 7, tempCondition.Length) & " ) " 'Gets clean and executable query condition (Details Above)
            '<--- FIX APPLY

            'finalQuery = "SELECT " & visibleColumn.Remove(visibleColumn.Length - 2) & " " & vbNewLine & _
            '"FROM " & currentTable & " " & vbNewLine & "WHERE " & filter & " " & or1 & or2 & or3 & vbNewLine & _
            'finalOrderStatement

            finalQuery = "SELECT " & visibleColumn.Remove(visibleColumn.Length - 2) & " " & vbNewLine & _
            "FROM " & currentTable & " " & vbNewLine & "WHERE " & realCondition & vbNewLine & _
            finalOrderStatement
        End If




        'visibleColumn.Remove(visibleColumn.Length - 2)
        'This Line Removes the Comma From the last Selected Column in FROM Clase (it's a Syntax Error if it is executed as-is)



        QueryBox.Text = finalQuery 'Finally The Assembled Query is ready to be executed

    End Sub

    Private Sub SaveAsXMLFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveAsXMLFileToolStripMenuItem.Click

        Dim conn As New OleDbConnection       'Connect to DB to get the schema
        conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filepath 'The connectionstring through the database file

        If str = Nothing Then
            MsgBox("No Dataset Loaded", MsgBoxStyle.Exclamation) 'If no dataset loaded, notify user
            Return 'Get out, don't go further

        End If

        Dim savepath As String 'This String holds the path to the file save location

        filesave.Title = "Save Dataset as XML file "
        filesave.InitialDirectory = "C:/" 'Start from C:/ as default search path
        filesave.Filter = "XML Format (*.xml)|*.xml" 'A pattern for saving as xml file 

        filesave.ShowDialog() 'Activate Dialog (Show)

        savepath = filesave.FileName 'The variable gets the path

        If filesave.FileName = "" Then 'If user does not proceed with saving (clicks cancel)
            Return 'Stop and get out (no exception will rise)
        End If

        Dim fstream As FileStream 'Declaring a filestream variable (initialization in try block)
        Dim writer As StreamWriter 'Declaring a StreamWriter variable (init in try block)

        Try
            fstream = New FileStream(savepath, FileMode.Create, FileAccess.Write) 'FileStream with savepath, file creation and write on it 
            writer = New StreamWriter(fstream) 'File Writer to a file, stream writer
            writer.WriteLine(str) 'Save xml data to xml file           
            writer.Close() 'Close Stream
            MsgBox("File Saved Sucessfully", MsgBoxStyle.Information) 'All Done
        Catch
            MsgBox("File write error", MsgBoxStyle.Critical) 'Throw a MsgBox is something goes wrong
            Return 'Get out

        End Try
        writer.Close() 'As long as you finish, close the file
    End Sub
    Private Sub qSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles qSave.Click
        qrySave.Show() 'Show Dialog QuerySave
    End Sub

    Private Sub qManage_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles qManage.Click
        qDbManager.Show() 'Show Form Query Manage
    End Sub

    Private Sub PreferencesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PreferencesToolStripMenuItem.Click
        Preferences.Show() 'Show Preferences Dialog
    End Sub

    Private Sub chMode_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chMode.Click
        CommandMode.cmdStatementBox.Text = QueryBox.Text 'send query box to command box
        Me.Hide() 'hide me
        CommandMode.Show() 'show command mode form

    End Sub
End Class
